home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
051-075
/
074
/
makemake
/
makemake.c
< prev
Wrap
C/C++ Source or Header
|
1995-03-13
|
7KB
|
256 lines
/*
*
* MakeMake - a program to construct a makefile from C source code
*
* Usage: makemake file1.c file2.c file3.c ... filen.c
*
* MakeMake reads the C source files and creates
* a file called 'makefile' in the current directory. For each
* source file entered on the command line, makemake adds an entry
* of the form:
*
* filex.o : filex.c ... header file list ...
* cc $(OPT) filex.c
*
* where the header file list is the transitive closure of all
* files #included in filex.c (i.e. if filex.c #includes "header.h", and
* "header.h" #includes "subheader.h", both "header.h" and "subheader.h"
* appear in the list of header files). MakeMake only examines header
* files delimited by double quotes ("). System header files enclosed
* in angle brackets (< and >) are not examined.
*
* The target of the makefile is assumed to be a program called 'main',
* with dependencies as shown:
*
* main : file1.o file2.o file3.o ... filek.o
* main : filek+1.o ... filen.o
* # ------- construction command goes here ---------
*
* At this point, the programmer should edit the resulting makefile
* to add the statement sequence which builds the program from the
* compiled object code by replacing the '#' comment line.
*
* The makefile has a hook for specifying compilation options through
* symbol OPT.
*
* Written and placed in the public domain by Tim McGrath 4/2/87
*
*/
#include <stdio.h>
#define LINEMAX 80
#define MAINPGM "main"
long malloc();
char *strcat(),*strcpy();
FILE *makefile;
main(argc,argv)
char **argv;
int argc;
{
int dependent_count;
char **dependents;
int i;
if ((makefile = fopen("makefile","w")) == 0L) {
puts("Can't create makefile"); exit(1);
}
fprintf(makefile,"OPT = \n\n");
depend_file(argc,argv,MAINPGM," ",".o");
for (i = 1; i < argc; i++) {
get_dependents(argv[i],&dependents,&dependent_count);
depend_file(dependent_count,dependents,argv[i],".o","");
free_space(dependents,dependent_count);
}
fclose(makefile); exit(0);
}
free_space(dp,dc)
/*
* Purpose: free up list of file names
* Inputs: dp - points to list of pointers to strings
* dc - number of pointers in the list
*/
char **dp;
int dc;
{
while (dc > 0) {
free(*dp++); dc--;
}
free(dp);
}
char *
file_exten(pgm_name,xtension,bufout)
/*
* Purpose: append new extension onto file name
* Inputs: pgm_name - pointer to name of file
* xtension - pointer to new file name extension (2 chars only)
* Outputs: bufout - points to area for new file name
* Returns: bufout
*/
char *pgm_name,*xtension,*bufout;
{
int i = 0;
while (*pgm_name) {
bufout[i++] = *pgm_name;
if (*pgm_name++ == '.' && xtension[0] != '\0') {
bufout[i++] = xtension[1];
break;
}
}
bufout[i] = '\0'; return(bufout);
}
depend_file(ct,flist,pgm_name,pgmx,filex)
/*
* Purpose: print file name and list of dependents
* Inputs: ct - number of dependents in the list
* flist - pointer to a list of pointers to dependent names
* pgm_name - name of file whose dependents are being printed
* pgmx - extension for pgm_name file (or "" if none)
* filex - extension for dependent file names (or "" if none)
*/
char **flist,*pgm_name,*pgmx,*filex;
int ct;
{
int i;
char buf[LINEMAX], add_name[LINEMAX], pname[LINEMAX];
start_line(file_exten(pgm_name,pgmx,pname),buf);
if (strcmp(pgm_name,MAINPGM)) strcat(strcat(buf," "),pgm_name);
for (i = 1; i < ct; i++) {
file_exten(flist[i],filex,add_name);
if (columns(buf)+strlen(add_name)+1 >= LINEMAX - 1) {
fputs(buf,makefile); fputc('\n',makefile);
start_line(file_exten(pgm_name,pgmx,pname),buf);
}
strcat(strcat(buf," "),add_name);
}
fputs(buf,makefile); fputc('\n',makefile);
if (strcmp(pgm_name,MAINPGM)) fprintf(makefile,"\tcc $(OPT) %s\n",pgm_name);
else {
fputs("# ------- construction command goes here ---------",makefile);
fputc('\n',makefile);
}
}
start_line(with_name,buf)
/*
* Purpose: give each line a standard indentation
* Inputs: with_name - name of root file on each line
* buf - place to put indented line
*/
char *with_name,*buf;
{
strcpy(buf,with_name); strcat(buf,"\t");
if (columns(buf) < 16) strcat(buf,"\t");
if (columns(buf) < 24) strcat(buf,"\t");
strcat(buf,":");
}
columns(s)
/*
* Purpose: count the number of columns a line spans
* Inputs: s - the characters in a line
* Returns: the number of columns (including tab expansion)
*/
char *s;
{
int col = 0;
while (*s) {
if (*s++ == '\t') while (++col & 7);
else ++col;
}
return(col);
}
get_dependents(fn,depv,depc)
/*
* Purpose: return a list of files depending on a C source file
* Inputs: fn - name of the c source file
* Outputs: depv - list of dependents (an array of pointers to filenames)
* depc - number of dependents
*/
char *fn,***depv;
int *depc;
{
char **lst;
int i;
lst = (char **) malloc(1024*sizeof(char *)); move_name(&lst[0],fn);
fputs(fn,stdout); fputc('\n',stdout); i = 0;
scan_file(lst,&i,fn); *depv = lst; *depc = i+1;
}
move_name(p,s)
/*
* Purpose: Allocate space for a new filename and copy it
* Inputs: p - location for new pointer to filename
* s - pointer to file name
*/
char **p,*s;
{
*p = (char *) malloc(strlen(s)+1); strcpy(*p,s);
}
scan_file(file_name_list,last_list_used,fn)
/*
* Purpose: search a C source file file #includes, and search the #includes
* for nested #includes
* Inputs: fn - name of file to scan
* Outputs: file_name_list - list of included files
* last_list_used - last used filename position in file_name_list
*/
char **file_name_list, *fn;
int *last_list_used;
{
FILE *fp,*fopen();
char buf[1024],ifn[LINEMAX];
int j,k;
fp = fopen(fn,"r");
if (!fp) { fprintf(stdout,"Couldn't open file %s\n",fn); return; }
while (fgets(buf,1024,fp)) {
if (strncmp(buf,"#include",8) == 0) {
j = 8;
while (buf[j] == ' ' || buf[j] == '\t') j++;
if (buf[j++] != '"') continue;
k = 0;
while (buf[j]) {
if (buf[j] == '"' || buf[j] == '\n') break;
else ifn[k++] = buf[j++];
}
ifn[k] = '\0';
if (add_name(file_name_list, last_list_used, ifn))
scan_file(file_name_list, last_list_used, ifn);
}
}
fclose(fp); return;
}
add_name(file_name_list, last_list_used, fn)
/*
* Purpose: Add a file name to the list if it's not there already
* Inputs: file_name_list - pointer to array of pointers to file names
* last_list_used - last element in array with a filename
* fn - name of file
* Returns: 1 if file name added, 0 otherwise
*/
char **file_name_list, *fn;
int *last_list_used;
{
int i;
for (i = 0; i <= *last_list_used; i++)
if (!strcmp(file_name_list[i],fn)) return(0);
*last_list_used += 1;
move_name(&file_name_list[*last_list_used],fn);
return(1);
}